<!--
 * @description: Description
 * @author: lizlong<94648929@qq.com>
 * @since: 2024-06-11 10:22:21
 * @LastAuthor: lizlong
 * @lastTime: 2024-06-11 17:26:51
-->

<script lang="ts" setup>
import { reactive, ref } from 'vue'

import va from '@/rules/index'
import { ConfigService } from '@/services/api/sys/config.service'
import type { FormInstance, FormRules } from 'element-plus'
import type {
  IFormDialogProps,
  IFormDialogTypeProps,
} from '@/components/sofastui/AdvancedForm/interface'
import { formDialogTitles } from '@/components/sofastui/AdvancedForm/constant'

type FormData = { id?: number } & Record<string, unknown>
type OptionItem = { title: string; id: number }

interface ShowOptions {
  type: IFormDialogTypeProps
  data?: FormData
  options?: OptionItem[]
}

const fileTypeOptions = [
  {
    label: '文本框',
    valueType: 'string',
    value: {
      type: 'input',
      props: {
        placeholder: '请输入',
        maxlength: 1000,
        showWordLimit: true,
      },
    },
  },
  {
    label: '数值框',
    valueType: 'number',
    value: {
      type: 'number',
      props: {
        placeholder: '请输入',
      },
    },
  },
  {
    label: '单选框',
    valueType: 'number',
    value: {
      type: 'radio',
      props: {
        options: [
          {
            label: '是',
            value: 1,
          },
          {
            label: '否',
            value: 0,
          },
        ],
      },
    },
  },
  {
    label: '多选框',
    valueType: 'array',
    value: {
      type: 'checkbox',
      props: {
        options: [
          {
            label: '选项1',
            value: 1,
          },
          {
            label: '选项2',
            value: 2,
          },
          {
            label: '选项3',
            value: 3,
          },
        ],
      },
    },
  },
]

const emits = defineEmits(['success'])

const formRef = ref<FormInstance>()

const saveLoading = ref<boolean>(false)
const formDialog = reactive<IFormDialogProps>({
  top: '15vh',
  width: '860px',
  type: 'add',
  title: '新增',
  span: 12,
  visible: false,
})
const formData = ref<{
  [key: string]: unknown
}>({})

const parentList = ref<
  {
    label: string
    value: string | number
  }[]
>([])
const formRules = reactive<FormRules>({
  title: [va.required()],
})

const fileTypeHandel = (item: {
  value: {
    [key: string]: unknown
  }
  valueType: string
}) => {
  formData.value.config = JSON.stringify(item.value)
  formData.value.valueType = item.valueType
}

const show = async ({ type, data = {}, options = [] }: ShowOptions): Promise<void> => {
  // Set dialog type
  formDialog.type = type
  formDialog.title = formDialogTitles[type]

  // Transform options for parent list
  parentList.value = options.map(({ title, id }) => ({
    label: title,
    value: id,
  }))

  try {
    // Handle different dialog types
    switch (type) {
      case 'add':
        formData.value = data
        break

      case 'update':
        if (data.id) {
          const res = await ConfigService.getObj(data.id)
          formData.value = res
        }
        break

      case 'view':
        if (data.id) {
          const res = await ConfigService.getObj(data.id)
          formData.value = res
        }
        break

      default:
        const exhaustiveCheck: never = type
        throw new Error(`Unhandled dialog type: ${exhaustiveCheck}`)
    }
  } catch (error) {
    console.log(error)
  }

  formDialog.visible = true
}

const saveForm = async (formRef: FormInstance | undefined) => {
  saveLoading.value = true
  if (!formRef) return
  try {
    await formRef.validate()
    if (formData.value?.id) {
      ConfigService.putObj(formData.value)
        .then(() => {
          saveSuccess('修改成功')
        })
        .catch(() => {
          saveLoading.value = false
        })
    } else {
      ConfigService.postObj(formData.value)
        .then(() => {
          saveSuccess('保存成功')
        })
        .catch(() => {
          saveLoading.value = false
        })
    }
  } catch (error) {
    console.log('error submit!!')
    console.log(error)
    saveLoading.value = false
  }
}
const saveSuccess = (message: string) => {
  ElMessage({
    type: 'success',
    message,
  })
  saveLoading.value = false
  formDialog.visible = false
  emits('success')
}

defineExpose({ show })
</script>

<template>
  <el-dialog
    :title="formDialog.title"
    v-model="formDialog.visible"
    :top="formDialog.top"
    :width="formDialog.width"
    :close-on-click-modal="false"
    :append-to-body="true"
    destroy-on-close
  >
    <el-form
      :model="formData"
      :rules="formRules"
      ref="formRef"
      label-width="80px"
      label-suffix=":"
      label-position="top"
    >
      <el-row :gutter="20">
        <el-col :span="formDialog.span">
          <el-form-item label="分组" prop="parentId">
            <el-select v-model="formData.parentId" placeholder="请选择" clearable>
              <el-option
                v-for="item in parentList"
                :label="item.label"
                :value="item.value"
                :key="item.value"
              />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="formDialog.span">
          <el-form-item label="名称" prop="title">
            <el-input v-model="formData.title" maxlength="50" placeholder="请输入名称" />
          </el-form-item>
        </el-col>
        <el-col :span="formDialog.span">
          <el-form-item label="KEY" prop="prop">
            <el-input v-model="formData.prop" maxlength="50" placeholder="请输入KEY" />
          </el-form-item>
        </el-col>
        <el-col :span="formDialog.span">
          <el-form-item label="排序" prop="orderNum">
            <el-input-number
              v-model="formData.orderNum"
              controls-position="right"
              class="w-full"
              style="width: 100%"
            ></el-input-number>
          </el-form-item>
        </el-col>
        <el-col :span="24" v-if="!!formData.parentId">
          <el-form-item label="默认值" prop="value">
            <el-input v-model="formData.value" placeholder="请输入值">
              <template #prepend>
                <el-select v-model="formData.valueType" placeholder="数据类型" style="width: 115px">
                  <el-option label="String" value="string" />
                  <el-option label="Number" value="number" />
                  <el-option label="Array" value="array" />
                </el-select>
              </template>
            </el-input>
          </el-form-item>
        </el-col>
        <el-col :span="24" v-if="!!formData.parentId">
          <el-form-item label="配置" prop="config">
            <div class="code-editor w-full">
              <div class="code-editor__wrapper">
                <div class="flex flex-col w-full">
                  <div
                    class="bg-gray-100 p-1 leading-none"
                    style="margin-left: -10px; margin-right: -10px"
                  >
                    <el-dropdown>
                      <el-button type="primary" size="small" text>导入配置</el-button>
                      <template #dropdown>
                        <el-dropdown-menu>
                          <el-dropdown-item
                            v-for="(item, index) in fileTypeOptions"
                            :key="index"
                            @click="fileTypeHandel(item)"
                            >{{ item.label }}</el-dropdown-item
                          >
                        </el-dropdown-menu>
                      </template>
                    </el-dropdown>
                  </div>
                  <div class="w-full">
                    <CodeEditor
                      v-model="formData.config"
                      language="json"
                      height="200px"
                      :editorOption="{
                        theme: 'vs',
                      }"
                    />
                  </div>
                </div>
              </div>
            </div>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button
          type="primary"
          @click="saveForm(formRef)"
          icon="CircleCheck"
          :loading="saveLoading"
          >保 存</el-button
        >
        <el-button @click="formDialog.visible = false" icon="CircleClose">取 消</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<style lang="less" scoped>
.code-editor {
  --el-input-text-color: var(--el-text-color-regular);
  --el-input-border: var(--el-border);
  --el-input-hover-border: var(--el-border-color-hover);
  --el-input-focus-border: var(--el-color-primary);
  --el-input-transparent-border: 0 0 0 1px transparent inset;
  --el-input-border-color: var(--el-border-color);
  --el-input-border-radius: var(--el-border-radius-base);
  --el-input-bg-color: var(--el-fill-color-blank);
  --el-input-icon-color: var(--el-text-color-placeholder);
  --el-input-placeholder-color: var(--el-text-color-placeholder);
  --el-input-hover-border-color: var(--el-border-color-hover);
  --el-input-clear-hover-color: var(--el-text-color-secondary);
  --el-input-focus-border-color: var(--el-color-primary);
  --el-input-width: 100%;
  --el-input-height: var(--el-component-size);
  box-sizing: border-box;
  display: inline-flex;
  font-size: var(--el-font-size-base);
  line-height: var(--el-input-height);
  position: relative;
  vertical-align: middle;
  width: var(--el-input-width);

  .code-editor__wrapper {
    align-items: center;
    background-color: var(--el-input-bg-color, var(--el-fill-color-blank));
    background-image: none;
    border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
    box-shadow: 0 0 0 1px var(--el-input-border-color, var(--el-border-color)) inset;
    cursor: text;
    display: inline-flex;
    flex-grow: 1;
    justify-content: center;
    padding: 1px 11px;
    transform: translateZ(0);
    transition: var(--el-transition-box-shadow);
  }
}
</style>
